<template>
  <div class="error-log">
    <el-page-header title="日志管理">
      <template #content>
        <span class="page-header-content">异常日志</span>
      </template>
    </el-page-header>

    <div class="log-content">
      <!-- 搜索栏 -->
      <el-card class="search-card">
        <el-form :model="searchForm" ref="searchFormRef" inline>
          <el-form-item label="异常类型" prop="exceptionType">
            <el-input
              v-model="searchForm.exceptionType"
              placeholder="请输入异常类型"
              clearable
            />
          </el-form-item>
          <el-form-item label="请求方法" prop="requestMethod">
            <el-select
              v-model="searchForm.requestMethod"
              placeholder="请选择请求方法"
              clearable
              style="width: 160px"
            >
              <el-option label="GET" value="GET" />
              <el-option label="POST" value="POST" />
              <el-option label="PUT" value="PUT" />
              <el-option label="DELETE" value="DELETE" />
            </el-select>
          </el-form-item>
          <el-form-item label="所属模块" prop="module">
            <el-select
              v-model="searchForm.module"
              placeholder="请选择所属模块"
              clearable
              style="width: 160px"
            >
              <el-option label="客户管理" value="客户管理" />
              <el-option label="贷款管理" value="贷款管理" />
              <el-option label="产品管理" value="产品管理" />
              <el-option label="系统管理" value="系统管理" />
              <el-option label="用户管理" value="用户管理" />
            </el-select>
          </el-form-item>
          <el-form-item label="异常时间" prop="timeRange">
            <el-date-picker
              v-model="searchForm.timeRange"
              type="datetimerange"
              range-separator="至"
              start-placeholder="开始时间"
              end-placeholder="结束时间"
              value-format="YYYY-MM-DD HH:mm:ss"
              :shortcuts="dateShortcuts"
            />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="handleSearch">查询</el-button>
            <el-button @click="handleReset">重置</el-button>
            <el-button type="success" @click="handleExport">导出日志</el-button>
          </el-form-item>
        </el-form>
      </el-card>

      <!-- 日志表格 -->
      <el-card class="table-card">
        <div class="table-header">
          <div class="left">
            <el-button 
              type="danger" 
              :disabled="selectedIds.length === 0" 
              @click="handleDeleteSelected"
            >
              批量删除
            </el-button>
          </div>
          <div class="right">
            <el-button type="danger" @click="handleClear">清空日志</el-button>
          </div>
        </div>

        <el-table
          :data="tableData"
          style="width: 100%"
          v-loading="loading"
          border
          stripe
          @selection-change="handleSelectionChange"
        >
          <el-table-column type="selection" width="55" />
          <el-table-column type="index" label="序号" width="60" align="center" />
          <el-table-column prop="exceptionType" label="异常类型" width="150" />
          <el-table-column prop="exceptionName" label="异常名称" width="150" />
          <el-table-column prop="requestMethod" label="请求方法" width="100" />
          <el-table-column prop="requestUrl" label="请求地址" min-width="200" show-overflow-tooltip />
          <el-table-column prop="userName" label="操作人" width="120" />
          <el-table-column prop="createTime" label="发生时间" width="180" />
          <el-table-column label="操作" width="150" fixed="right">
            <template #default="scope">
              <el-button
                link
                type="primary"
                @click="handleViewDetail(scope.row)"
              >
                详情
              </el-button>
              <el-button
                link
                type="danger"
                @click="handleDelete(scope.row)"
              >
                删除
              </el-button>
            </template>
          </el-table-column>
        </el-table>

        <div class="pagination">
          <el-pagination
            v-model:current-page="currentPage"
            v-model:page-size="pageSize"
            :page-sizes="[10, 20, 50, 100]"
            :total="total"
            layout="total, sizes, prev, pager, next, jumper"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
          />
        </div>
      </el-card>

      <!-- 详情弹窗 -->
      <el-dialog
        v-model="detailVisible"
        title="异常日志详情"
        width="800px"
        destroy-on-close
      >
        <el-descriptions :column="2" border>
          <el-descriptions-item label="异常类型">
            {{ currentLog.exceptionType }}
          </el-descriptions-item>
          <el-descriptions-item label="异常名称">
            {{ currentLog.exceptionName }}
          </el-descriptions-item>
          <el-descriptions-item label="操作人">
            {{ currentLog.userName }}
          </el-descriptions-item>
          <el-descriptions-item label="发生时间">
            {{ currentLog.createTime }}
          </el-descriptions-item>
          <el-descriptions-item label="请求方法">
            {{ currentLog.requestMethod }}
          </el-descriptions-item>
          <el-descriptions-item label="请求地址">
            {{ currentLog.requestUrl }}
          </el-descriptions-item>
          <el-descriptions-item label="异常信息" :span="2">
            <div class="error-message">{{ currentLog.exceptionMessage }}</div>
          </el-descriptions-item>
          <el-descriptions-item label="异常堆栈" :span="2">
            <pre class="stack-trace">{{ currentLog.exceptionStackTrace }}</pre>
          </el-descriptions-item>
          <el-descriptions-item label="请求参数" :span="2">
            <pre class="code-block">{{ formatJson(currentLog.requestParams) }}</pre>
          </el-descriptions-item>
        </el-descriptions>
      </el-dialog>
    </div>
  </div>
</template>

<script>
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { exceptionLogApi } from '@/api/monitor'

export default {
  name: 'ErrorLog',
  setup() {
    // 搜索表单
    const searchForm = reactive({
      exceptionType: '',
      requestMethod: '',
      module: '',
      timeRange: [],
      pageNum: 1,
      pageSize: 10
    })

    // 日期快捷选项
    const dateShortcuts = [
      {
        text: '最近一小时',
        value: () => {
          const end = new Date()
          const start = new Date()
          start.setTime(start.getTime() - 3600 * 1000)
          return [start, end]
        }
      },
      {
        text: '今天',
        value: () => {
          const end = new Date()
          const start = new Date()
          start.setHours(0, 0, 0, 0)
          return [start, end]
        }
      },
      {
        text: '最近三天',
        value: () => {
          const end = new Date()
          const start = new Date()
          start.setTime(start.getTime() - 3600 * 1000 * 24 * 3)
          return [start, end]
        }
      },
      {
        text: '最近一周',
        value: () => {
          const end = new Date()
          const start = new Date()
          start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
          return [start, end]
        }
      }
    ]

    // 表格数据
    const loading = ref(false)
    const currentPage = ref(1)
    const pageSize = ref(10)
    const total = ref(0)
    const tableData = ref([])
    const selectedIds = ref([])

    // 详情弹窗
    const detailVisible = ref(false)
    const currentLog = ref({})

    // 格式化JSON
    const formatJson = (json) => {
      if (!json) return ''
      try {
        if (typeof json === 'string') {
          return JSON.stringify(JSON.parse(json), null, 2)
        }
        return JSON.stringify(json, null, 2)
      } catch (e) {
        return json
      }
    }

    // 获取异常日志列表
    const getExceptionLogList = () => {
      loading.value = true
      // 处理时间范围
      const params = { ...searchForm }
      if (params.timeRange && params.timeRange.length === 2) {
        params.startTime = params.timeRange[0]
        params.endTime = params.timeRange[1]
      }
      delete params.timeRange

      exceptionLogApi.getList(params).then(res => {
        if (res.code === 200) {
          tableData.value = res.data.rows
          total.value = res.data.total
        } else {
          ElMessage.error(res.msg || '获取异常日志列表失败')
        }
        loading.value = false
      }).catch(() => {
        loading.value = false
        ElMessage.error('获取异常日志列表失败')
      })
    }

    // 查询
    const handleSearch = () => {
      searchForm.pageNum = 1
      getExceptionLogList()
    }

    // 重置
    const handleReset = () => {
      searchForm.exceptionType = ''
      searchForm.requestMethod = ''
      searchForm.module = ''
      searchForm.timeRange = []
      handleSearch()
    }

    // 导出
    const handleExport = () => {
      ElMessage.success('日志导出成功')
    }

    // 查看详情
    const handleViewDetail = (row) => {
      currentLog.value = row
      detailVisible.value = true
    }

    // 表格选择
    const handleSelectionChange = (selection) => {
      selectedIds.value = selection.map(item => item.id)
    }

    // 删除单条日志
    const handleDelete = (row) => {
      ElMessageBox.confirm('确定要删除该异常日志吗？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        exceptionLogApi.deleteExceptionLog(row.id).then(res => {
          if (res.code === 200) {
            ElMessage.success('删除成功')
            getExceptionLogList()
          } else {
            ElMessage.error(res.msg || '删除失败')
          }
        }).catch(() => {
          ElMessage.error('删除失败')
        })
      }).catch(() => {})
    }

    // 批量删除日志
    const handleDeleteSelected = () => {
      if (selectedIds.value.length === 0) {
        ElMessage.warning('请至少选择一条记录')
        return
      }
      ElMessageBox.confirm(`确定要删除选中的${selectedIds.value.length}条异常日志吗？`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        exceptionLogApi.deleteExceptionLog(selectedIds.value.join(',')).then(res => {
          if (res.code === 200) {
            ElMessage.success('批量删除成功')
            getExceptionLogList()
          } else {
            ElMessage.error(res.msg || '批量删除失败')
          }
        }).catch(() => {
          ElMessage.error('批量删除失败')
        })
      }).catch(() => {})
    }

    // 清空日志
    const handleClear = () => {
      ElMessageBox.confirm('确定要清空所有异常日志吗？此操作不可恢复！', '警告', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        exceptionLogApi.cleanExceptionLog().then(res => {
          if (res.code === 200) {
            ElMessage.success('清空异常日志成功')
            getExceptionLogList()
          } else {
            ElMessage.error(res.msg || '清空异常日志失败')
          }
        }).catch(() => {
          ElMessage.error('清空异常日志失败')
        })
      }).catch(() => {})
    }

    // 分页
    const handleSizeChange = (val) => {
      searchForm.pageSize = val
      getExceptionLogList()
    }

    const handleCurrentChange = (val) => {
      searchForm.pageNum = val
      getExceptionLogList()
    }

    // 组件挂载时获取列表
    onMounted(() => {
      getExceptionLogList()
    })

    return {
      searchForm,
      dateShortcuts,
      loading,
      currentPage,
      pageSize,
      total,
      tableData,
      selectedIds,
      detailVisible,
      currentLog,
      formatJson,
      handleSearch,
      handleReset,
      handleExport,
      handleViewDetail,
      handleSelectionChange,
      handleDelete,
      handleDeleteSelected,
      handleClear,
      handleSizeChange,
      handleCurrentChange
    }
  }
}
</script>

<style scoped>
.error-log {
  padding: 20px;
}

.page-header-content {
  font-size: 20px;
  font-weight: bold;
}

.log-content {
  margin-top: 20px;
}

.search-card {
  margin-bottom: 20px;
}

.table-card {
  margin-bottom: 20px;
}

.table-header {
  margin-bottom: 15px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.pagination {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
}

.error-message {
  color: #f56c6c;
  background-color: #fef0f0;
  padding: 8px;
  border-radius: 4px;
  white-space: pre-wrap;
  word-break: break-all;
}

.stack-trace {
  margin: 0;
  padding: 8px;
  background-color: #f5f7fa;
  border-radius: 4px;
  font-family: monospace;
  white-space: pre-wrap;
  word-break: break-all;
  max-height: 300px;
  overflow-y: auto;
}

.code-block {
  margin: 0;
  padding: 8px;
  background-color: #f5f7fa;
  border-radius: 4px;
  font-family: monospace;
  white-space: pre-wrap;
  word-break: break-all;
}

:deep(.el-card__body) {
  padding: 20px;
}
</style> 